home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / MCASM.RAR / MC_ASM.EXE / WROX_ASM / CH12 / FORMATS / MAPPER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-14  |  10.4 KB  |  337 lines

  1. /* color mapping with splitted color palette */
  2. #ifndef MAPPER_H
  3. #define MAPPER_H
  4.  
  5. #include <mem.h>
  6. #include <math.h>
  7. #include <alloc.h>
  8. #include "common.h"
  9. #include "graph.h"
  10. #include "mapper.h"
  11.  
  12. color_mapper::color_mapper(int colors_,int width_,BGRpalette colormap) {
  13.     int i;
  14.  
  15.     initialized = TRUE;
  16.     on_odd_row = FALSE;
  17.     actual_number_of_colors =  colors_;
  18.     memmove(my_colormap,colormap,actual_number_of_colors*sizeof(colortype));
  19.     width = width_;
  20.     for (i = 0; i < 3 ; i++) {
  21.         error[i] = NULL;
  22.         next_line_error[i] = NULL;
  23.         }
  24. }
  25.  
  26. color_mapper::~color_mapper() {
  27.     int i;
  28.  
  29.     for (i = 0; i < 3 ; i++) {
  30.         if (error[i] != NULL) delete error[i];
  31.         if (next_line_error[i] != NULL) delete next_line_error[i];
  32.         }
  33.  
  34. }
  35.  
  36. color_mapper::prepare_dithering() {
  37.     int i;
  38.  
  39.     for (i = 0; i < 3; i++) {
  40.         error[i] = new int[width + 2];
  41.         next_line_error[i] = new int[width + 2];
  42.         if ((error[i] == NULL) || (next_line_error[i] == NULL)) return(-1);
  43.         memset(error[i],0,sizeof(int)*(width + 2));
  44.         }
  45.     return(1);
  46. }
  47.  
  48. // ==================  splitted colors
  49.  
  50. void color_mapper_splitted::init(int width_,BYTE *color_values[3],
  51.                          BYTE color_num_[3]){
  52.     int i,j, col, r,g,b ;
  53.  
  54.     initialized = FALSE;
  55.     width = width_;
  56.     actual_number_of_colors =  1;
  57.     for (i = 0; i < 3; i++) {
  58.         color_num[i] = color_num_[i];
  59.         actual_number_of_colors *=  color_num[i];
  60.         }
  61.     if (actual_number_of_colors > 256) return;
  62.     col = 0;
  63.     for (r = 0; r < color_num[0]; r++)
  64.         for (g = 0; g < color_num[1]; g++)
  65.             for (b = 0; b < color_num[2]; b++) {
  66.                 my_colormap[col].r = color_values[0][r];
  67.                 my_colormap[col].g = color_values[1][g];
  68.                 my_colormap[col++].b = color_values[2][b];
  69.             }
  70.  
  71.     if  (prepare_dithering() < 0) return;
  72.     for (i = 0; i < 3; i++) prepare_table(color_values[i], i);
  73.     initialized = TRUE;
  74. }
  75.  
  76. void color_mapper_splitted::prepare_table(BYTE *values,int color_index) {
  77.     int i,j, thres, prev_thres, val, num, multipl;
  78.     BYTE *table,*value_tab;
  79.  
  80.     convert_table0[color_index] = new BYTE[3*256+1];
  81.     convert_table[color_index] = &convert_table0[color_index][256];
  82.  
  83.     table = convert_table[color_index];
  84.     num =  color_num[color_index];
  85.     prev_thres = -257;
  86.     for (i = 0; i < num-1; i++) {
  87.            thres = (values[i] + values[i+1]) / 2;
  88.            for (j = prev_thres+1; j <= thres; j++) table[j] = i;
  89.            prev_thres = thres;
  90.            }
  91.     for (j = prev_thres+1; j <= 2*256; j++) table[j] = num -1;
  92.     value_tab = new BYTE[num];
  93.     for (i = 0; i < num; i++) value_tab[i] = values[i];
  94.     value_table[color_index] =  value_tab;
  95.     max_color_value = max(max_color_value,value_tab[num-1]);
  96. }
  97.  
  98.  
  99.  
  100. int color_mapper_splitted::select_colors_num(int max_colors) {
  101.   /* based on procedure from Independent JPEG Group's software */
  102.   /* Determine allocation of desired colors to components, */
  103.   /* and fill in color_num[] array to indicate choice. */
  104.  
  105.   int nc,total_colors, iroot, i;
  106.   long temp;
  107.   BOOL changed;
  108.  
  109.   if ((max_colors < 8) || (max_colors > 256)) return(-1);
  110.  
  111.   /* We can allocate at least the nc'th root of max_colors per component. */
  112.   /* Compute floor(nc'th root of max_colors). */
  113.  
  114.   nc = 3;
  115.   iroot = 1;
  116.   do {
  117.     iroot++;
  118.     temp = iroot;        /* set temp = iroot ** nc */
  119.     for (i = 1; i < nc; i++)
  120.       temp *= iroot;
  121.   } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
  122.   iroot--;                /* now iroot = floor(root) */
  123.  
  124.     /* We provide a special policy for quantizing in RGB space.
  125.      * If 256 colors are requested, we allocate 8 red, 8 green, 4 blue levels;
  126.      * this corresponds to the common 3/3/2-bit scheme.  For other totals,
  127.      * the counts are set so that the number of colors allocated to each
  128.      * component are roughly in the proportion R 3, G 4, B 2.
  129.      * For low color counts, it's easier to hardwire the optimal choices
  130.      * than try to tweak the algorithm to generate them.
  131.      */
  132.     if (max_colors == 256) {
  133.       color_num[0] = 8;  color_num[1] = 8;  color_num[2] = 4;
  134.       return 1;
  135.     }
  136.  
  137.     if (max_colors < 12) {
  138.       /* Fixed mapping for 8 colors */
  139.       color_num[0] = color_num[1] = color_num[2] = 2;
  140.     } else if (max_colors < 18) {
  141.       /* Fixed mapping for 12 colors */
  142.       color_num[0] = 2;  color_num[1] = 3;  color_num[2] = 2;
  143.     } else if (max_colors < 36) {
  144.       /* Fixed mapping for 18 colors */
  145.       color_num[0] = 3;  color_num[1] = 3;  color_num[2] = 2;
  146.     } else {
  147.       /* these weights are readily derived with a little algebra */
  148.       color_num[0] = (iroot * 266) >> 8; /* R weight is 1.0400 */
  149.       color_num[1] = (iroot * 355) >> 8; /* G weight is 1.3867 */
  150.       color_num[2] = (iroot * 177) >> 8; /* B weight is 0.6934 */
  151.     }
  152.     total_colors = color_num[0] * color_num[1] * color_num[2];
  153.     /* The above computation produces "floor" values, so we may be able to
  154.      * increment the count for one or more components without exceeding
  155.      * max_colors.  We try in the order B, G, R.
  156.      */
  157.     do {
  158.       changed = FALSE;
  159.       for (i = 2; i >= 0; i--) {
  160.     /* calculate new total_colors if color_num[i] is incremented */
  161.     temp = total_colors / color_num[i];
  162.     temp *= color_num[i]+1;    /* done in long arith to avoid oflo */
  163.     if (temp <= (long) max_colors) {
  164.       color_num[i]++;        /* OK, apply the increment */
  165.       total_colors = (int) temp;
  166.       changed = TRUE;
  167.     }
  168.       }
  169.     } while (changed);        /* loop until no increment is possible */
  170.  
  171.   return(1);
  172. }
  173.  
  174. color_mapper_splitted::color_mapper_splitted(int width_,BYTE *color_values[3],
  175.                          BYTE color_num_[3]){
  176.     max_color_value = 0;
  177.     color_mapper_splitted::init(width_,color_values,color_num_);
  178. }
  179. //    short cut
  180. color_mapper_splitted::color_mapper_splitted(int colors_,int width_,int max_color_value_) {
  181.     int i,j,c_num;
  182.     BYTE val[3][10];
  183.     BYTE *vp[3];
  184.     max_color_value = max_color_value_;
  185.     initialized = FALSE;
  186.     if  ((max_color_value > 255) || (select_colors_num(colors_) < 0)) return;
  187.     for (i = 0; i < 3; i++) {
  188.         val[i][0] = 0;
  189.         c_num = color_num[i];
  190.         val[i][c_num-1] = max_color_value;
  191.         for (j = 1; j < c_num-1; j++)
  192.              val[i][j] = (max_color_value*j) / (c_num - 1);
  193.     }
  194.     for (i = 0; i < 3; i++) vp[i] = val[i];
  195.     color_mapper_splitted::init(width_,vp,color_num);
  196.     initialized = TRUE;
  197. }
  198.  
  199.  
  200. color_mapper_splitted::~color_mapper_splitted() {
  201.     int i;
  202.     for (i = 0; i < 3; i++) {
  203.         if (convert_table[i] != NULL) delete convert_table0[i];
  204.         if (value_table[i] != NULL) delete value_table[i];
  205.     }
  206. }
  207.  
  208.  
  209. void color_mapper_splitted:: process_line(BYTE *R, BYTE *G, BYTE *B, BYTE *out_line) {
  210.     memset(out_line,0,width); // initialize output to process componentes separately
  211.     process_one_color(R, out_line, 0);
  212.     process_one_color(G, out_line, 1);
  213.     process_one_color(B, out_line, 2);
  214.     on_odd_row = (on_odd_row ? FALSE : TRUE);
  215. }
  216.  
  217. void color_mapper_splitted::process_one_color(BYTE *in, BYTE *out_line, int col_ind) {
  218.   register int val;
  219.   int two_val,multipl,i;
  220.   register int *thisrowerr, *nextrowerr;
  221.   int *swp;
  222.   BYTE *convert_tab, *value_tab;
  223.   register int pixcode;
  224.   int column;
  225.   int dir; /* 1 for left-to-right, -1 for right-to-left */
  226.  
  227.   thisrowerr = error[col_ind] + 1;
  228.   nextrowerr = next_line_error[col_ind] + width;
  229.   convert_tab = convert_table[col_ind];
  230.   value_tab = value_table[col_ind];
  231.  
  232.   if (on_odd_row) {
  233.     /* work right to left in this row */
  234.     dir = -1;
  235.     in += width-1;
  236.     out_line += width-1;
  237.       } else {
  238.     /* work left to right in this row */
  239.     dir = 1;
  240.       }
  241.  
  242.   multipl = 1;
  243.   for (i = col_ind+1; i < 3; i++) multipl *=color_num[i];
  244.   *nextrowerr = 0;        /* need only initialize this one entry */
  245.  
  246.   for (column = width; column > 0; column--) {
  247.     /* Get accumulated error for this component, round to integer.
  248.      * (error was scaled in 16 times)
  249.      * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
  250.      * for either sign of the error value.
  251.      */
  252.     val = *in + ((*thisrowerr + 8) >> 4);
  253.     /* Compute pixel value + error compensation,
  254.      *  Note max error value is +- MAXJSAMPLE.
  255.      */
  256.  
  257.     pixcode = convert_tab[val];  // partial color index
  258.  
  259.     /* Select output value, accumulate into output code for this pixel */
  260.  
  261.     if (col_ind == 0)  *out_line = pixcode;
  262.     else *out_line += multipl*pixcode;
  263.  
  264.     /* Compute actual representation error at this pixel */
  265.     /* Note: we can do this even though we don't yet have the final */
  266.     /* value of pixcode, because the colormap is orthogonal. */
  267.     val -= value_tab[pixcode];
  268.     /* Propagate error to (same component of) adjacent pixels */
  269.     /* Remember that nextrowerr entries are in reverse order! */
  270.     two_val = val << 1;    // *2
  271.     nextrowerr[-1]  = val; /* not +=, since not initialized yet */
  272.     val += two_val;        /* form error * 3 */
  273.     nextrowerr[ 1] += val;
  274.     val += two_val;        /* form error * 5 */
  275.     nextrowerr[ 0] += val;
  276.     val += two_val;        /* form error * 7 */
  277.     thisrowerr[ 1] += val;
  278.     in += dir;    /* advance input ptr to next column */
  279.     out_line += dir;    /* advance output ptr to next column */
  280.     thisrowerr++;        /* cur-row error ptr advances to right */
  281.     nextrowerr--;        /* next-row error ptr advances to left */
  282.       }
  283.   swp = error[col_ind];
  284.   error[col_ind] = next_line_error[col_ind];          // swap pointers for future
  285.   next_line_error[col_ind] = swp;
  286. }
  287.  
  288.  
  289. color_mapper_gray::color_mapper_gray(int colors_,int width_,int max_color_value_) {
  290.     int i,j, col;
  291.     BYTE val[256];
  292.  
  293.     initialized = FALSE;
  294.     max_color_value = max_color_value_;
  295.     if  ((max_color_value > 255) || (colors_ > 255)) return;
  296.  
  297.     width = width_;
  298.     actual_number_of_colors =  colors_;
  299.  
  300.     color_num[0] =   colors_;
  301.     color_num[1] = 1; color_num[2] = 1; // it's important!
  302.     val[0] = 0;
  303.     val[colors_-1] = max_color_value;
  304.     for (j = 1; j < colors_-1; j++)
  305.              val[j] = (max_color_value*j) / (colors_ - 1);
  306.  
  307.     col = 0;
  308.     for (col = 0; col < colors_; col++) {
  309.         my_colormap[col].r = val[col];
  310.         my_colormap[col].g = val[col];
  311.         my_colormap[col].b = val[col];
  312.         }
  313.  
  314.  
  315.         error[0] = new int[width + 2];
  316.         next_line_error[0] = new int[width + 2];
  317.         if ((error[0] == NULL) || (next_line_error[0] == NULL)) return;
  318.         memset(error[0],0,sizeof(int)*(width + 2));
  319.  
  320.         error[1] =  error[2] = NULL;
  321.         next_line_error[1] = next_line_error[2] = NULL;
  322.         value_table[1] = value_table[2]    = NULL;
  323.         convert_table0[1] = convert_table0[2]    = NULL;
  324.  
  325.     prepare_table(val, 0);
  326.     initialized = TRUE;
  327. }
  328.  
  329. void color_mapper_gray:: process_line(BYTE *source,BYTE *out_line) {
  330.     memset(out_line,0,width); // initialize output to process componentes separately
  331.     process_one_color(source, out_line, 0);
  332.     on_odd_row = (on_odd_row ? FALSE : TRUE);
  333.  
  334. }
  335.  
  336. #endif
  337.